import { useStorage } from '@vueuse/core';
import useUserStore from '@/store/user';
import { useRuoyiStore } from '@/store/ruoyi';
import { systemDictDataService } from '@great/services';
import pinyin from 'pinyin';

// 日期格式化
export function parseTime(time: any, pattern?: string) {
    if (arguments.length === 0 || !time) {
        return null;
    }
    const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
    let date;
    if (typeof time === 'object') {
        date = time;
    } else {
        if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
            time = parseInt(time);
        } else if (typeof time === 'string') {
            time = time
                .replace(new RegExp(/-/gm), '/')
                .replace('T', ' ')
                .replace(new RegExp(/\.[\d]{3}/gm), '');
        }
        if (typeof time === 'number' && time.toString().length === 10) {
            time = time * 1000;
        }
        date = new Date(time);
    }
    const formatObj: { [key: string]: any } = {
        y: date.getFullYear(),
        m: date.getMonth() + 1,
        d: date.getDate(),
        h: date.getHours(),
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    };
    return format.replace(/{(y|m|d|h|i|s|a)+}/g, (result: string, key: string) => {
        let value = formatObj[key];
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') {
            return ['日', '一', '二', '三', '四', '五', '六'][value];
        }
        if (result.length > 0 && value < 10) {
            value = '0' + value;
        }
        return value || 0;
    });
}

/**
 * 添加日期范围
 * @param params
 * @param dateRange
 * @param propName
 */
export const addDateRange = (params: any, dateRange: any[], propName?: string) => {
    const search = params;
    search.params =
        typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params)
            ? search.params
            : {};
    dateRange = Array.isArray(dateRange) ? dateRange : [];
    if (typeof propName === 'undefined') {
        search.params['beginTime'] = dateRange[0];
        search.params['endTime'] = dateRange[1];
    } else {
        search.params['begin' + propName] = dateRange[0];
        search.params['end' + propName] = dateRange[1];
    }
    return search;
};

// 回显数据字典
export const selectDictLabel = (datas: any, value: number | string) => {
    if (value === undefined) {
        return '';
    }
    const actions: Array<string | number> = [];
    Object.keys(datas).some(key => {
        if (datas[key].value == '' + value) {
            actions.push(datas[key].label);
            return true;
        }
    });
    if (actions.length === 0) {
        actions.push(value);
    }
    return actions.join('');
};

// 回显数据字典（字符串数组）
export const selectDictLabels = (datas: any, value: any, separator: any) => {
    if (value === undefined || value.length === 0) {
        return '';
    }
    if (Array.isArray(value)) {
        value = value.join(',');
    }
    const actions: any[] = [];
    const currentSeparator = undefined === separator ? ',' : separator;
    const temp = value.split(currentSeparator);
    Object.keys(value.split(currentSeparator)).some(val => {
        let match = false;
        Object.keys(datas).some(key => {
            if (datas[key].value == '' + temp[val]) {
                actions.push(datas[key].label + currentSeparator);
                match = true;
            }
        });
        if (!match) {
            actions.push(temp[val] + currentSeparator);
        }
    });
    return actions.join('').substring(0, actions.join('').length - 1);
};

// 字符串格式化(%s )
export function sprintf(str: string) {
    if (arguments.length !== 0) {
        let flag = true,
            i = 1;
        str = str.replace(/%s/g, function () {
            const arg = arguments[i++];
            if (typeof arg === 'undefined') {
                flag = false;
                return '';
            }
            return arg;
        });
        return flag ? str : '';
    }
}

// 转换字符串，undefined,null等转化为""
export const parseStrEmpty = (str: any) => {
    if (!str || str == 'undefined' || str == 'null') {
        return '';
    }
    return str;
};

// 数据合并
export const mergeRecursive = (source: any, target: any) => {
    for (const p in target) {
        try {
            if (target[p].constructor == Object) {
                source[p] = mergeRecursive(source[p], target[p]);
            } else {
                source[p] = target[p];
            }
        } catch (e) {
            source[p] = target[p];
        }
    }
    return source;
};

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export const handleTree = <T>(data: any[], id?: string, parentId?: string, children?: string): T[] => {
    const config: {
        id: string;
        parentId: string;
        childrenList: string;
    } = {
        id: id || 'id',
        parentId: parentId || 'parentId',
        childrenList: children || 'children'
    };

    const childrenListMap: any = {};
    const tree: T[] = [];
    for (const d of data) {
        const id = d[config.id];
        childrenListMap[id] = d;
        if (!d[config.childrenList]) {
            d[config.childrenList] = [];
        }
    }

    for (const d of data) {
        const parentId = d[config.parentId];
        const parentObj = childrenListMap[parentId];
        if (!parentObj) {
            tree.push(d);
        } else {
            parentObj[config.childrenList].push(d);
        }
    }
    return tree;
};

/**
 * 参数处理
 * @param {*} params  参数
 */
export const tansParams = (params: any) => {
    let result = '';
    for (const propName of Object.keys(params)) {
        const value = params[propName];
        const part = encodeURIComponent(propName) + '=';
        if (value !== null && value !== '' && typeof value !== 'undefined') {
            if (typeof value === 'object') {
                for (const key of Object.keys(value)) {
                    if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
                        const params = propName + '[' + key + ']';
                        const subPart = encodeURIComponent(params) + '=';
                        result += subPart + encodeURIComponent(value[key]) + '&';
                    }
                }
            } else {
                result += part + encodeURIComponent(value) + '&';
            }
        }
    }
    return result;
};

// 返回项目路径
export const getNormalPath = (p: string): string => {
    if (p.length === 0 || !p || p === 'undefined') {
        return p;
    }
    const res = p.replace('//', '/');
    if (res[res.length - 1] === '/') {
        return res.slice(0, res.length - 1);
    }
    return res;
};

// 验证是否为blob格式
export const blobValidate = (data: any) => {
    return data.type !== 'application/json';
};

export default {
    handleTree
};

// auth.ts
const TokenKey = 'token';

const tokenStorage = useStorage<null | string>(TokenKey, null);

export const getToken = () => tokenStorage.value;

export const setToken = (access_token: string) => (tokenStorage.value = access_token);

export const removeToken = () => (tokenStorage.value = null);

// request.ts
export const globalHeaders = () => {
    return {
        Authorization: 'Bearer ' + getToken(),
        clientid: RUOYI_CLIENT_ID
    };
};
//

/**
 * 字符权限校验
 * @param {Array} value 校验值
 * @returns {Boolean}
 */
export const checkPermi = (value: any) => {
    if (value && value instanceof Array && value.length > 0) {
        const permissions = useUserStore().permissions;
        const permissionDatas = value;
        const all_permission = '*:*:*';

        const hasPermission = permissions.some(permission => {
            return all_permission === permission || permissionDatas.includes(permission);
        });

        if (!hasPermission) {
            return false;
        }
        return true;
    } else {
        console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`);
        return false;
    }
};

/**
 * 角色权限校验
 * @param {Array} value 校验值
 * @returns {Boolean}
 */
export const checkRole = (value: any): boolean => {
    if (value && value instanceof Array && value.length > 0) {
        const roles = useUserStore().roles;
        const permissionRoles = value;
        const super_admin = 'admin';

        const hasRole = roles.some(role => {
            return super_admin === role || permissionRoles.includes(role);
        });

        if (!hasRole) {
            return false;
        }
        return true;
    } else {
        console.error(`need roles! Like checkRole="['admin','editor']"`);
        return false;
    }
};

/**
 * 获取字典数据
 */
export const useDict = (...args: string[]): { [key: string]: any[] } => {
    const res = ref<{
        [key: string]: any[];
    }>({});

    args.forEach(async dictType => {
        res.value[dictType] = [];
        const dicts = useRuoyiStore().getDict(dictType);
        if (dicts) {
            res.value[dictType] = dicts;
        } else {
            await systemDictDataService.getDicts(dictType).then(resp => {
                res.value[dictType] = resp.data.map((p): any => ({
                    label: p.dictLabel,
                    value: p.dictValue,
                    elTagType: p.listClass,
                    elTagClass: p.cssClass
                }));
                useRuoyiStore().setDict(dictType, res.value[dictType]);
            });
        }
    });
    return res.value;
};
// propTypes.ts
import type { CSSProperties } from 'vue';
import VueTypes, { createTypes, toValidableType } from 'vue-types';
import type { VueTypeValidableDef, VueTypesInterface } from 'vue-types';

type PropTypes = VueTypesInterface & {
    readonly style: VueTypeValidableDef<CSSProperties>;
    readonly fieldOption: VueTypeValidableDef<Array<any>>;
};

const propTypes = createTypes({
    func: undefined,
    bool: undefined,
    string: undefined,
    number: undefined,
    object: undefined,
    integer: undefined
}) as PropTypes;

export class ProjectTypes extends VueTypes {
    static get style() {
        return toValidableType('style', {
            type: [String, Object],
            default: undefined
        });
    }
}
export { propTypes };

/**
 * scroll-to.ts
 */
const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
    t /= d / 2;
    if (t < 1) {
        return (c / 2) * t * t + b;
    }
    t--;
    return (-c / 2) * (t * (t - 2) - 1) + b;
};

// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
const requestAnimFrame = (function () {
    return (
        window.requestAnimationFrame ||
        (window as any).webkitRequestAnimationFrame ||
        (window as any).mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        }
    );
})();

/**
 * Because it's so fucking difficult to detect the scrolling element, just move them all
 * @param {number} amount
 */
const move = (amount: number) => {
    document.documentElement.scrollTop = amount;
    (document.body.parentNode as HTMLElement).scrollTop = amount;
    document.body.scrollTop = amount;
};

const position = () => {
    return (
        document.documentElement.scrollTop ||
        (document.body.parentNode as HTMLElement).scrollTop ||
        document.body.scrollTop
    );
};

/**
 * @param {number} to
 * @param {number} duration
 * @param {Function} callback
 */
export const scrollTo = (to: number, duration: number, callback?: any) => {
    const start = position();
    const change = to - start;
    const increment = 20;
    let currentTime = 0;
    duration = typeof duration === 'undefined' ? 500 : duration;
    const animateScroll = function () {
        // increment the time
        currentTime += increment;
        // find the value with the quadratic in-out easing function
        const val = easeInOutQuad(currentTime, start, change, duration);
        // move the document.body
        move(val);
        // do the animation unless its over
        if (currentTime < duration) {
            requestAnimFrame(animateScroll);
        } else {
            if (callback && typeof callback === 'function') {
                // the animation is done so lets callback
                callback();
            }
        }
    };
    animateScroll();
};

/**
 * 汉字转成拼音首字母
 * @param {string} rawStr 原始字符串
 * @return {string} 拼音首字母字符串
 */
export const getPinyinInitials = (rawStr: string = ''): string => {
    let result = '';
    if (rawStr) {
        for (let i = 0; i < rawStr.length; i++) {
            const char = rawStr[i];
            // 检查是否是汉字
            if (/[\u4e00-\u9fa5]/.test(char)) {
                // 如果是汉字，转换为拼音首字母
                const pinyinArr = pinyin(char, {
                    style: pinyin.STYLE_FIRST_LETTER,
                    heteronym: false
                });
                result += (pinyinArr.flat()[0] || '').toUpperCase();
            } else {
                // 如果不是汉字，保留原始字符（包括大小写）
                result += char;
            }
        }
    }
    return result;
};
